package dk.dtu.android.transport;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONObject;

import dk.dtu.android.transport.db.BaseDbAdapter;
import dk.dtu.android.transport.db.PendingRequestTable;

import android.util.Log;

public class TransportAPI {
	
	public final static String URL = "http://transport.amsi.me/api";
	public static String userId = null;
	
	public static String post(String url, JSONObject jsonObj, boolean queueOnFailure) throws Exception
	{
		return post(url, jsonObj.toString(), queueOnFailure);
	}
	
	public static String post(String url, String json, boolean queueOnFailure) throws Exception
	{
		try
		{
			return RestClient.post(url, json);
		} 
		catch (Exception e)
		{
			Log.d("TransportAPI", "Error occured during post: " + e.getMessage() + "\n" + exceptionToString(e));
			if (queueOnFailure)
			{
				PendingRequestTable.insert(url, json);
			}
			throw e;
		}
	}
	
	public static Boolean facebookLogin(String fuserId)
	{
		try
		{
			JSONObject param = new JSONObject();
			param.put("fuser_id", fuserId);
			String response = RestClient.post(URL + "/facebook_login/", param);
			Log.d("Transport", "facebookLogin response: " + response.toString());
			JSONObject jsonResponse = new JSONObject(response);
			if (jsonResponse.getBoolean("success"))
			{
				userId = jsonResponse.getString("user_id");
				return true;
			}
			else
			{
				return false;
			}
		}
		catch (Exception e)
		{
			reportError("TransportAPI", "Error in facebookLogin: ", e);
			return null;
		}
	}
	
	public static Boolean facebookInformation(String fuserId, String name, String email, String link)
	{
		try
		{
			JSONObject param = new JSONObject();
			param.put("fuser_id", fuserId);
			param.put("name", name);
			param.put("email", email);
			param.put("link", link);
			String response = RestClient.post(URL + "/facebook_information/", param);
			Log.d("Transport", "facebookInformation response: " + response.toString());
			JSONObject jsonResponse = new JSONObject(response);
			if (jsonResponse.getBoolean("success"))
			{
				userId = jsonResponse.getString("user_id");
				return true;
			}
			else
			{
				return false;
			}
		}
		catch (Exception e)
		{
			reportError("TransportAPI", "Error in faebbokInformation: ", e);
			return null;
		}
	}
	
	public static Boolean logGPS(String x, String y, Date timestamp)
	{
		try
			{
			JSONObject param = new JSONObject();
			String timestampString = Helpers.ToXMLDate(timestamp);
			param.put("user_id", userId);
			param.put("x", x);
			param.put("y", y);
			param.put("timestamp", timestampString);
			
			String response = post(URL + "/log_gps/", param, true);
			JSONObject jsonResponse = new JSONObject(response);
			if (jsonResponse.getBoolean("success"))
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		catch (Exception e)
		{
			try {
			  reportError("TransportAPI", "Error sending log: ", e);
			return null;
			}
			catch (Exception ee)
			{
				Log.d("TransportAPI", "--------------------------------------------------------");
				Log.d("TransportAPI", "Another bug occourd! " + ee.getMessage() + "\n" + exceptionToString(ee));
				return null;
			}
		}
	}
	
	public static String exceptionToString(Exception e)
	{
		StringWriter sw = new StringWriter();
		e.printStackTrace(new PrintWriter(sw));
		return sw.toString();	
	}
	
	public static Boolean reportError(String tag, String message, Exception e)
	{
		
		return reportError(tag, message + "\n\n" + e.getMessage() + "\n" + exceptionToString(e));
	}
	
	public static Boolean reportError(String tag, String message)
	{
		try
		{
			Log.e(tag, message);
			JSONObject param = new JSONObject();
			param.put("message", message + "\n\nVersion: " + BaseDbAdapter.DATABASE_VERSION);
			param.put("tag", tag);
			if (userId != null)
			{
				param.put("user_id", userId);
			}
			String response = post(URL + "/report_error/", param, true);
			JSONObject jsonResponse = new JSONObject(response);
			if (jsonResponse.getBoolean("success"))
			{
				return true;
			}
			else
			{
				return false;
			}
		}
		catch (Exception e)
		{
			Log.e("TransportAPI", "ERROR sending error report, error was: ", e);
			return null;
		}
	}
	
	public static void sendPendingRequests()
	{
		PendingRequestTable.sendUnsent();
	}
	
	public static JSONObject getPrediction(String x, String y, Date pTime){
		try
		{
			List<NameValuePair> params = new LinkedList<NameValuePair>();
			params.add(new BasicNameValuePair("x", x));
			params.add(new BasicNameValuePair("y", y));
			params.add(new BasicNameValuePair("user_id", userId));
			params.add(new BasicNameValuePair("ptime", Helpers.ToXMLDate(pTime)));
			String response = RestClient.get(URL + "/get_prediction/", params);
			JSONObject jsonResponse = new JSONObject(response);
			if (jsonResponse.getBoolean("success") && jsonResponse.getBoolean("found"))
			{
				Log.d("PREDICTION", "--------------------------------------");
				Log.d("PREDICTION", "Got: " + jsonResponse.getString("y") + " " + jsonResponse.getString("x"));
				return jsonResponse;
			}
		}
		catch (Exception e)
		{
			Log.d("TransportAPI", "Something went wrong getting a prediction" + e.getMessage() + "\n" + exceptionToString(e));
		}
		return null;
	}
}
